using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using dnAnalytics.LinearAlgebra;
using dnAnalytics.LinearAlgebra.IO;
using NUnit.Framework;

namespace dnAnalytics.UnitTests.LinearAlgebra.IO
{
    [TestFixture]
    [Category("Managed")]
    public class DelimitedMatrixWriterTest
    {
        [Test]
        public void WriteMatrixString()
        {
            //white space
            DelimitedMatrixReader dmr = new DelimitedMatrixReader();
            Matrix matrix = dmr.ReadMatrix("../../TestMatrices/random_real_general_dense_10_20.space");

            DelimitedMatrixWriter dmw = new DelimitedMatrixWriter();
            dmw.WriteMatrix(matrix, "../../TestMatrices/temp_string.comma");
            dmr = new DelimitedMatrixReader(",");
            Matrix test = dmr.ReadMatrix("../../TestMatrices/temp_string.comma");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            double expected = 767.35692;
            double actual = matrix.FrobeniusNorm();
            double error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);

            dmw = new DelimitedMatrixWriter("\t");
            dmw.WriteMatrix(matrix, "../../TestMatrices/temp_string.tab");
            dmr = new DelimitedMatrixReader("\t");
            test = dmr.ReadMatrix("../../TestMatrices/temp_string.tab");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);

            dmw = new DelimitedMatrixWriter(" ");
            dmr = new DelimitedMatrixReader();
            dmw.WriteMatrix(matrix, "../../TestMatrices/temp_string.space");
            test = dmr.ReadMatrix("../../TestMatrices/temp_string.space");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);
        }

        [Test]
        public void WriteMatrixStringFormat()
        {
            String format = "E";
            //white space
            DelimitedMatrixReader dmr = new DelimitedMatrixReader();
            Matrix matrix = dmr.ReadMatrix("../../TestMatrices/random_real_general_dense_10_20.space");

            DelimitedMatrixWriter dmw = new DelimitedMatrixWriter();
            dmw.WriteMatrix(matrix, "../../TestMatrices/temp_string_format.comma", format);
            dmr = new DelimitedMatrixReader(",");
            Matrix test = dmr.ReadMatrix("../../TestMatrices/temp_string_format.comma");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            double expected = 767.35692;
            double actual = matrix.FrobeniusNorm();
            double error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);

            dmw = new DelimitedMatrixWriter("\t");
            dmw.WriteMatrix(matrix, "../../TestMatrices/temp_string_format.tab", format);
            dmr = new DelimitedMatrixReader("\t");
            test = dmr.ReadMatrix("../../TestMatrices/temp_string_format.tab");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);

            dmw = new DelimitedMatrixWriter(" ");
            dmr = new DelimitedMatrixReader();
            dmw.WriteMatrix(matrix, "../../TestMatrices/temp_string_format.space", format);
            test = dmr.ReadMatrix("../../TestMatrices/temp_string_format.space");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);
        }

        [Test]
        public void WriteMatrixStream()
        {
            //white space
            DelimitedMatrixReader dmr = new DelimitedMatrixReader();
            Matrix matrix = dmr.ReadMatrix("../../TestMatrices/random_real_general_dense_10_20.space");

            DelimitedMatrixWriter dmw = new DelimitedMatrixWriter();
            dmw.WriteMatrix(matrix, File.OpenWrite("../../TestMatrices/temp_stream.comma"));
            dmr = new DelimitedMatrixReader(",");
            Matrix test = dmr.ReadMatrix("../../TestMatrices/temp_stream.comma");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            double expected = 767.35692;
            double actual = matrix.FrobeniusNorm();
            double error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);

            dmw = new DelimitedMatrixWriter("\t");
            dmw.WriteMatrix(matrix, File.OpenWrite("../../TestMatrices/temp_stream.tab"));
            dmr = new DelimitedMatrixReader("\t");
            test = dmr.ReadMatrix("../../TestMatrices/temp_stream.tab");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);

            dmw = new DelimitedMatrixWriter(" ");
            dmr = new DelimitedMatrixReader();
            dmw.WriteMatrix(matrix, File.OpenWrite("../../TestMatrices/temp_stream.space"));
            test = dmr.ReadMatrix("../../TestMatrices/temp_stream.space");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);
        }

        [Test]
        public void WriteMatrixStreamFormat()
        {
            String format = "E";
            //white space
            DelimitedMatrixReader dmr = new DelimitedMatrixReader();
            Matrix matrix = dmr.ReadMatrix("../../TestMatrices/random_real_general_dense_10_20.space");

            DelimitedMatrixWriter dmw = new DelimitedMatrixWriter();
            dmw.WriteMatrix(matrix, File.OpenWrite("../../TestMatrices/temp_stream_format.comma"), format);
            dmr = new DelimitedMatrixReader(",");
            Matrix test = dmr.ReadMatrix("../../TestMatrices/temp_stream_format.comma");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            double expected = 767.35692;
            double actual = matrix.FrobeniusNorm();
            double error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);

            dmw = new DelimitedMatrixWriter("\t");
            dmw.WriteMatrix(matrix, File.OpenWrite("../../TestMatrices/temp_stream_format.tab"), format);
            dmr = new DelimitedMatrixReader("\t");
            test = dmr.ReadMatrix("../../TestMatrices/temp_stream_format.tab");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);

            dmw = new DelimitedMatrixWriter(" ");
            dmr = new DelimitedMatrixReader();
            dmw.WriteMatrix(matrix, File.OpenWrite("../../TestMatrices/temp_stream_format.space"), format);
            test = dmr.ReadMatrix("../../TestMatrices/temp_stream_format.space");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);
        }

        [Test]
        public void WriteMatrixTextWriter()
        {
            //white space
            DelimitedMatrixReader dmr = new DelimitedMatrixReader();
            Matrix matrix = dmr.ReadMatrix("../../TestMatrices/random_real_general_dense_10_20.space");

            DelimitedMatrixWriter dmw = new DelimitedMatrixWriter();
            using (TextWriter tw = new StreamWriter("../../TestMatrices/temp_writer.comma"))
            {
                dmw.WriteMatrix(matrix, tw);
            }
            dmr = new DelimitedMatrixReader(",");
            Matrix test = dmr.ReadMatrix("../../TestMatrices/temp_writer.comma");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            double expected = 767.35692;
            double actual = matrix.FrobeniusNorm();
            double error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);

            dmw = new DelimitedMatrixWriter("\t");
            using (TextWriter tw = new StreamWriter("../../TestMatrices/temp_writer.tab"))
            {
                dmw.WriteMatrix(matrix, tw);
            }
            dmr = new DelimitedMatrixReader("\t");
            test = dmr.ReadMatrix("../../TestMatrices/temp_writer.tab");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);

            dmw = new DelimitedMatrixWriter(" ");
            dmr = new DelimitedMatrixReader();
            using (TextWriter tw = new StreamWriter("../../TestMatrices/temp_writer.space"))
            {
                dmw.WriteMatrix(matrix, tw);
            }
            test = dmr.ReadMatrix("../../TestMatrices/temp_writer.space");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);
        }

        [Test]
        public void WriteMatrixTextWriterFormat()
        {
            String format = "E";
            //white space
            DelimitedMatrixReader dmr = new DelimitedMatrixReader();
            Matrix matrix = dmr.ReadMatrix("../../TestMatrices/random_real_general_dense_10_20.space");

            DelimitedMatrixWriter dmw = new DelimitedMatrixWriter();
            using (TextWriter tw = new StreamWriter("../../TestMatrices/temp_writer.comma"))
            {
                dmw.WriteMatrix(matrix, tw, format);
            }
            dmr = new DelimitedMatrixReader(",");
            Matrix test = dmr.ReadMatrix("../../TestMatrices/temp_writer.comma");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            double expected = 767.35692;
            double actual = matrix.FrobeniusNorm();
            double error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);

            dmw = new DelimitedMatrixWriter("\t");
            using (TextWriter tw = new StreamWriter("../../TestMatrices/temp_writer.tab"))
            {
                dmw.WriteMatrix(matrix, tw, format);
            }
            dmr = new DelimitedMatrixReader("\t");
            test = dmr.ReadMatrix("../../TestMatrices/temp_writer.tab");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);

            dmw = new DelimitedMatrixWriter(" ");
            dmr = new DelimitedMatrixReader();
            using (TextWriter tw = new StreamWriter("../../TestMatrices/temp_writer.space"))
            {
                dmw.WriteMatrix(matrix, tw, format);
            }
            test = dmr.ReadMatrix("../../TestMatrices/temp_writer.space");
            Assert.AreEqual(10, test.Rows);
            Assert.AreEqual(20, test.Columns);
            actual = matrix.FrobeniusNorm();
            error = System.Math.Abs((actual - expected) / expected);
            Assert.IsTrue(error < Constants.IO_ACCEPTABLE_ERROR);
        }
    }
}
